package com.linzi.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Month;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;


/**
 * 时间与日期工具
 *
 * @author chenmaolin
 */

@Slf4j
@SuppressWarnings("ALL")
public class DateHelper {

    private static String defaultDateFormat = "yyyy-MM-dd";
    private static String defaultTimeFormat = "HH:mm:ss";
    private static String defaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    private static Locale defaultLocale = Locale.CHINA;

    public static void setDefaultDateFormat(String format) {
        DateHelper.defaultDateFormat = format;
    }

    public static String getCurrentTimeStampString() {
        String time = DateHelper.formatDateTime(new Date(), "yyyyMMddHHmmssSSS", Locale.CHINA);
        return time;
    }

    public static String getCurrentTimeString() {
        String time = DateHelper.formatDateTime(new Date(), "yyyyMMddHHmmss", Locale.CHINA);
        return time;
    }

    public static String getCurrentDayString() {
        String time = DateHelper.formatDateTime(new Date(), "yyyyMMdd", Locale.CHINA);
        return time;
    }

    public static String getDefaultDateFormat() {
        return defaultDateFormat;
    }

    public static void setDefaultTimeFormat(String defaultTimeFormat) {
        DateHelper.defaultTimeFormat = defaultTimeFormat;
    }

    public static String getDefaultTimeFormat() {
        return defaultTimeFormat;
    }

    public static void setDefaultDateTimeFormat(String defaultDateTimeFormat) {
        DateHelper.defaultDateTimeFormat = defaultDateTimeFormat;
    }

    public static String getDefaultDateTimeFormat() {
        return defaultDateTimeFormat;
    }

    public static void setDefaultLocal(Locale locale) {
        DateHelper.defaultLocale = locale;
    }

    public static Locale getDefaultLocal() {
        return defaultLocale;
    }

    public static Date getCurrent() {
        return new Date(System.currentTimeMillis());
    }


    /**
     * 获取明天的日期
     *
     * @return
     */
    public static Date getTomorrowDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, 1);
        return calendar.getTime();
    }

    /**
     * 获取后天的日期
     *
     * @return
     */
    public static Date getAfterTomorrowDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, 2);
        return calendar.getTime();
    }

    /**
     * 获取大后天的日期
     *
     * @return
     */
    public static Date getAfterDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, 3);
        return calendar.getTime();
    }


    /**
     * 获取年
     *
     * @return
     */
    public static Integer getYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 获取月份
     *
     * @return
     */
    public static Integer getMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH) + 1;
    }

    public static Integer getDay() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DATE);
    }


    /**
     * 格式化日期时间
     *
     * @param calendar 时间
     * @param format   格式
     * @param locale   地域
     * @return
     */
    public static String formatDateTime(Calendar calendar, String format,
                                        Locale locale) {
        SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
        return sdf.format(calendar.getTime());
    }

    /**
     * 格式化日期时间
     *
     * @param date   时间
     * @param format 格式
     * @param locale 地域
     * @return
     */
    public static String formatDateTime(Date date, String format, Locale locale) {
        SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
        return sdf.format(date);
    }

    /**
     * 格式化日期时间
     *
     * @param date   时间
     * @param format 格式
     * @param locale 地域
     * @return
     */
    public static String formatDateTime(Date date) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(defaultDateTimeFormat, defaultLocale);
        return sdf.format(date);
    }

    /**
     * 取当前服务器上的日期。使用默认日期格式。<br />
     * 在没有改变的情况下.默认格式为"yyyy-MM-dd".
     *
     * @return
     */
    public static String getCurrentDate() {
        return formatDateTime(getCurrent(), getDefaultDateFormat(), getDefaultLocal());
    }

    /**
     * 取当前服务器上的时间.使用默认时间格式.<br />
     * 在没有改变的情况下.默认格式为"HH:mm:ss".
     *
     * @return
     */
    public static String getCurrentTime() {
        return formatDateTime(getCurrent(), getDefaultTimeFormat(), getDefaultLocal());
    }

    /**
     * 取当前服务器上的日期时间.使用默认日期时间格式.<br />
     * 在没有改变的情况下.默认格式为"yyyy-MM-dd HH:mm:ss".
     *
     * @return
     */
    public static String getCurrentDateTime() {
        return formatDateTime(getCurrent(), getDefaultDateTimeFormat(),
                getDefaultLocal());
    }

    /**
     * 转换Date为Timestamp.
     *
     * @param date
     * @return
     */
    public static Timestamp getTimestamp(Date date) {
        return new Timestamp(date.getTime());
    }

    /**
     * 转换Timestamp为Date.
     *
     * @param timestamp
     * @return
     */
    public static Date getDate(Timestamp timestamp) {
        return new Date(timestamp.getTime());
    }

    /**
     * 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数
     *
     * @param date
     * @return
     */
    public static long getTime(Date date) {
        return date.getTime();
    }

    /**
     * 使用指定的格式和地域解析字段串为时间
     *
     * @param format 格式
     * @param locale 地域
     * @param str    字段串
     * @return
     */
    public static Date parseDateTime(String format, Locale locale, String str) {
        SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
        try {
            return sdf.parse(str);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 使用默认值解析表示日期时间的字符
     *
     * @param str
     * @return
     */
    public static Date parseDateTime(String str) {
        return parseDateTime(getDefaultDateTimeFormat(), getDefaultLocal(), str);
    }

    /**
     * 使用默认值解析表示日期的字符
     *
     * @param str
     * @return
     */
    public static Date parseDate(String str) {
        return parseDateTime(getDefaultDateFormat(), getDefaultLocal(), str);
    }

    /**
     * 使用默认值解析表示时间的字符
     *
     * @param str
     * @return
     */
    public static Date parseTime(String str) {
        return parseDateTime(getDefaultTimeFormat(), getDefaultLocal(), str);
    }

    /**
     * 使用指定格式取指定时间的月首
     *
     * @param format
     * @return
     */
    public static String getMonthStart(Date date, String format) {
        Calendar localTime = Calendar.getInstance(getDefaultLocal());
        localTime.setTime(date);
        localTime.set(Calendar.DAY_OF_MONTH, 1);
        return formatDateTime(localTime, format, getDefaultLocal());
    }

    /**
     * 使用指定格式取指定时间的月末
     *
     * @return
     */
    public static String getMonthEnd(Date date, String format) {
        Calendar localTime = Calendar.getInstance(getDefaultLocal());
        localTime.setTime(date);
        localTime.add(Calendar.MONTH, 1);
        localTime.set(Calendar.DAY_OF_MONTH, 1);
        localTime.add(Calendar.DAY_OF_MONTH, -1);
        return formatDateTime(localTime, format, getDefaultLocal());
    }

    /**
     * 对指定时间进行增减操作后返回指定格式的时间串
     *
     * @param date          指定的时间
     * @param calendarField 在{@link Calendar}类定义的字段
     * @param amount        增加数量
     * @param format        指定格式
     * @return
     */
    public static String addDateTime(Date date, int calendarField, int amount,
                                     String format) {
        Calendar localTime = Calendar.getInstance(getDefaultLocal());
        localTime.setTime(date);
        localTime.add(calendarField, amount);
        return formatDateTime(localTime, format, getDefaultLocal());
    }

    /**
     * 比较两个时间的顺序
     *
     * @param src
     * @param dst
     * @return 如果src在dst之前则 小于0<br />
     * 如果src在dst之后则 大于0<br />
     * 如果相同则 等于0
     */
    public static int comparaDateTime(Date src, Date dst) {
        return src.compareTo(dst);
    }

    /**
     * 将日期的时分秒部分去掉
     *
     * @param date
     * @return
     */
    public static Date truncateTime(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal.getTime();
    }

    /**
     * 将日期的时分秒部分去掉
     *
     * @param date
     * @return
     */
    public static Calendar truncateTime(Calendar cal) {
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal;
    }

    /**
     * 将java.util.Date转换成java.sql.Date
     *
     * @param date
     * @return
     */
    public static java.sql.Date transfer2SqlDate(Date date) {
        return new java.sql.Date(date.getTime());
    }

    /**
     * java.util.Date转成java.sql.Timestamp
     *
     * @param date
     * @return
     */
    public static Timestamp transfer2Timestamp(Date date) {
        return new Timestamp(date.getTime());
    }

    public static Date AddDate(Date date, int DateField, int num) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(DateField, num);

        return cal.getTime();
    }

    public static Date getLastDateOfMonth(Date date) {
        Date truncdate = truncateTime(date);
        Calendar cal = Calendar.getInstance();
        cal.setTime(truncdate);
        int maxday = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
//		System.out.println(maxday);

        cal.set(Calendar.DAY_OF_MONTH, maxday);
        return cal.getTime();
    }

    /**
     * 获取时间下任意个整点
     *
     * @param date     时间
     * @param format   格式
     * @param nextHour 下几个整点
     * @return
     */
    public static Date nextHourTime(Date date, int nextHour) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(Calendar.MINUTE, 0);
        ca.set(Calendar.SECOND, 0);
        ca.set(Calendar.HOUR_OF_DAY, ca.get(Calendar.HOUR_OF_DAY) + nextHour);
        return ca.getTime();
    }

    /**
     * 获取  星期几   多少号   多好月
     *
     * @param arg Calendar.DAY_OF_WEEK Calendar.DAY_OF_MONTH  Calendar.MONTH
     * @return
     */
    public static int get(int arg) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        if (arg == Calendar.DAY_OF_MONTH) {
            return cal.get(Calendar.DAY_OF_MONTH);
        }
        if (arg == Calendar.DAY_OF_WEEK) {
            int temp = cal.get(Calendar.DAY_OF_WEEK);
            if (temp == 1) {
                return 7;
            }
            if (temp == 7) {
                return 1;
            } else {
                return temp - 1;
            }
        }
        if (arg == Calendar.MONTH) {
            return cal.get(Calendar.MONTH) + 1;
        }
        if (arg == Calendar.HOUR_OF_DAY) {
            return cal.get(Calendar.HOUR_OF_DAY);
        }
        return 0;

    }

    public static int get(Date d, int arg) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(d.getTime());
        if (arg == Calendar.DAY_OF_MONTH) {
            return cal.get(Calendar.DAY_OF_MONTH);
        }
        if (arg == Calendar.DAY_OF_WEEK) {
            int temp = cal.get(Calendar.DAY_OF_WEEK);
            if (temp == 1) {
                return 7;
            }
            if (temp == 7) {
                return 1;
            } else {
                return temp - 1;
            }
        }
        if (arg == Calendar.MONTH) {
            return cal.get(Calendar.MONTH) + 1;
        }
        if (arg == Calendar.HOUR_OF_DAY) {
            return cal.get(Calendar.HOUR_OF_DAY);
        }
        return 0;

    }

    /**
     * 判断时间格式 格式必须为“YYYY-MM-dd”
     *
     * @param sDate
     * @return
     */
    public static boolean isLegalDate(String sDate) {
        int legalLen = 10;
        if ((sDate == null) || (sDate.length() != legalLen)) {
            return false;
        }

        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = formatter.parse(sDate);
            return sDate.equals(formatter.format(date));
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 计算相差天数
     *
     * @param before
     * @param before
     * @return
     */
    public static long daysBetween(Date before, Date after) {
        long difference = (after.getTime() - before.getTime()) / 86400000;
        return difference;
    }

    /**
     * 获取当前日期所在季度的开始日期和结束日期
     * 季度一年四季， 第一季度：1月-3月， 第二季度：4月-6月， 第三季度：7月-9月， 第四季度：10月-12月
     *
     * @param isFirst true表示查询本季度开始日期  false表示查询本季度结束日期
     * @return
     */
    public static LocalDate getStartOrEndDayOfQuarter(Boolean isFirst) {
        LocalDate today = LocalDate.now();
        LocalDate resDate = LocalDate.now();
        if (today == null) {
            today = resDate;
        }
        Month month = today.getMonth();
        Month firstMonthOfQuarter = month.firstMonthOfQuarter();
        Month endMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
        if (isFirst) {
            resDate = LocalDate.of(today.getYear(), firstMonthOfQuarter, 1);
        } else {
            resDate = LocalDate.of(today.getYear(), endMonthOfQuarter, endMonthOfQuarter.length(today.isLeapYear()));
        }
        return resDate;
    }

    /**
     * 给时间加上几个小时
     *
     * @param date 时间 格式：yyyy-MM-dd HH:mm:ss
     * @param hour 小时
     * @return
     */
    public static Date addDateHour(Date date, int hour) {
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, hour);// 24小时制
        return cal.getTime();
    }

    /**
     * 判断时间是否是今天
     *
     * @param str
     * @param formatStr
     * @return
     * @throws Exception
     */
    public static boolean isToday(Date date) {
        Calendar c1 = Calendar.getInstance();
        c1.setTime(date);
        int year1 = c1.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH) + 1;
        int day1 = c1.get(Calendar.DAY_OF_MONTH);
        Calendar c2 = Calendar.getInstance();
        c2.setTime(new Date());
        int year2 = c2.get(Calendar.YEAR);
        int month2 = c2.get(Calendar.MONTH) + 1;
        int day2 = c2.get(Calendar.DAY_OF_MONTH);
        if (year1 == year2 && month1 == month2 && day1 == day2) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(DateHelper.get(Calendar.MONTH));
//		String datestr = "2010-04-01";
//		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//		Date d = simpleDateFormat.parse(datestr);
//		System.out.println(getLastDateOfMonth(d));
//		
//		System.out.println(DateHelper.getCurrentTimeStampString());

        System.out.println(DateHelper.addDateHour(new Date(), 5));
        System.out.println(DateHelper.getCurrentDateTime());
        System.out.println(DateHelper.getCurrentDate());

        System.out.println(DateHelper.getTomorrowDay());

        System.out.println(DateHelper.getAfterDay());

        Date date = parseDate("2023-7-13");

        System.out.println(isToday(date));
    }

}
